From 6d53c2339f79baa0b295ecc614f41f9daab2e132 Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Tue, 18 Dec 2012 02:06:12 -0500 Subject: [PATCH] Use minimum/natural size semantics MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Rewrites gtk_tree_view_column_request_width() and gtk_tree_view_size_allocate_columns() to respect the minimum and natural sizes that are already being returned by gtk_cell_area_context_get_preferred_width(). The convoluted logic explained (not!) by this comment has been removed: “Only update the expand value if the width of the widget has changed, or the number of expand columns has changed, or if there are no expand columns, or if we didn't have an size-allocation yet after the last validated node.” This logic seems to have been a workaround for the “jumping” behavior fixed in 16195ad and is no longer necessary. https://bugzilla.gnome.org/show_bug.cgi?id=691751 --- gtk/gtktreeprivate.h | 4 +- gtk/gtktreeview.c | 170 ++++++++++++++++------------------------ gtk/gtktreeviewcolumn.c | 62 +++++++-------- 3 files changed, 101 insertions(+), 135 deletions(-) diff --git a/gtk/gtktreeprivate.h b/gtk/gtktreeprivate.h index 9817c5c8c1..fcdcf81b22 100644 --- a/gtk/gtktreeprivate.h +++ b/gtk/gtktreeprivate.h @@ -106,7 +106,9 @@ void _gtk_tree_view_column_unrealize_button (GtkTreeViewColumn *column); void _gtk_tree_view_column_set_tree_view (GtkTreeViewColumn *column, GtkTreeView *tree_view); -gint _gtk_tree_view_column_request_width (GtkTreeViewColumn *tree_column); +void _gtk_tree_view_column_request_width (GtkTreeViewColumn *tree_column, + gint *minimum, + gint *natural); void _gtk_tree_view_column_allocate (GtkTreeViewColumn *tree_column, int x_offset, int width); diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index 871a8e4062..d0b06e9423 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -385,10 +385,10 @@ struct _GtkTreeViewPrivate gint drag_pos; gint x_drag; - /* Non-interactive Header Resizing, expand flag support */ - gint last_extra_space; - gint last_extra_space_per_column; - gint last_number_of_expand_columns; + /* Column width allocation */ + gint minimum_width; + gint natural_width; + gint n_expand_columns; /* ATK Hack */ GtkTreeDestroyCountFunc destroy_count_func; @@ -492,8 +492,6 @@ struct _GtkTreeViewPrivate guint in_grab : 1; - guint post_validation_flag : 1; - /* Whether our key press handler is to avoid sending an unhandled binding to the search entry */ guint search_entry_avoid_unhandled_binding : 1; @@ -1719,6 +1717,9 @@ gtk_tree_view_init (GtkTreeView *tree_view) tree_view->priv->header_height = 1; tree_view->priv->x_drag = 0; tree_view->priv->drag_pos = -1; + tree_view->priv->minimum_width = 0; + tree_view->priv->natural_width = 0; + tree_view->priv->n_expand_columns = 0; tree_view->priv->header_has_focus = FALSE; tree_view->priv->pressed_button = -1; tree_view->priv->press_start_x = -1; @@ -1751,8 +1752,6 @@ gtk_tree_view_init (GtkTreeView *tree_view) tree_view->priv->tooltip_column = -1; - tree_view->priv->post_validation_flag = FALSE; - tree_view->priv->last_button_x = -1; tree_view->priv->last_button_y = -1; @@ -2395,12 +2394,16 @@ gtk_tree_view_get_preferred_width (GtkWidget *widget, GtkTreeView *tree_view = GTK_TREE_VIEW (widget); GList *list; GtkTreeViewColumn *column; - gint width = 0; + gint column_minimum, column_natural; /* we validate some rows initially just to make sure we have some size. * In practice, with a lot of static lists, this should get a good width. */ do_validate_rows (tree_view, FALSE); + + tree_view->priv->minimum_width = 0; + tree_view->priv->natural_width = 0; + tree_view->priv->n_expand_columns = 0; /* keep this in sync with size_allocate below */ for (list = tree_view->priv->columns; list; list = list->next) @@ -2409,10 +2412,18 @@ gtk_tree_view_get_preferred_width (GtkWidget *widget, if (!gtk_tree_view_column_get_visible (column) || column == tree_view->priv->drag_column) continue; - width += _gtk_tree_view_column_request_width (column); + _gtk_tree_view_column_request_width (column, &column_minimum, &column_natural); + tree_view->priv->minimum_width += column_minimum; + tree_view->priv->natural_width += column_natural; + + if (gtk_tree_view_column_get_expand (column)) + tree_view->priv->n_expand_columns++; } - *minimum = *natural = width; + if (minimum != NULL) + *minimum = tree_view->priv->minimum_width; + if (natural != NULL) + *natural = tree_view->priv->natural_width; } static void @@ -2427,7 +2438,10 @@ gtk_tree_view_get_preferred_height (GtkWidget *widget, height = tree_view->priv->height + gtk_tree_view_get_effective_header_height (tree_view); - *minimum = *natural = height; + if (minimum != NULL) + *minimum = height; + if (natural != NULL) + *natural = height; } static int @@ -2459,12 +2473,9 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget, GList *list, *first_column, *last_column; GtkTreeViewColumn *column; GtkAllocation widget_allocation; - gint width = 0; - gint extra, extra_per_column, extra_for_last; - gint full_requested_width = 0; - gint number_of_expand_columns = 0; + gint minimum_width, natural_width, n_expand_columns, width; + gint column_minimum, column_natural, column_width; gboolean rtl; - gboolean update_expand; tree_view = GTK_TREE_VIEW (widget); @@ -2484,111 +2495,65 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget, rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL); - /* find out how many extra space and expandable columns we have */ - for (list = tree_view->priv->columns; list != last_column->next; list = list->next) - { - column = (GtkTreeViewColumn *)list->data; - - if (!gtk_tree_view_column_get_visible (column) || column == tree_view->priv->drag_column) - continue; - - full_requested_width += _gtk_tree_view_column_request_width (column); - - if (gtk_tree_view_column_get_expand (column)) - number_of_expand_columns++; - } - - /* Only update the expand value if the width of the widget has changed, - * or the number of expand columns has changed, or if there are no expand - * columns, or if we didn't have an size-allocation yet after the - * last validated node. - */ - update_expand = (width_changed && *width_changed == TRUE) - || number_of_expand_columns != tree_view->priv->last_number_of_expand_columns - || number_of_expand_columns == 0 - || tree_view->priv->post_validation_flag == TRUE; - - tree_view->priv->post_validation_flag = FALSE; - gtk_widget_get_allocation (widget, &widget_allocation); - if (!update_expand) - { - extra = tree_view->priv->last_extra_space; - extra_for_last = MAX (widget_allocation.width - full_requested_width - extra, 0); - } - else - { - extra = MAX (widget_allocation.width - full_requested_width, 0); - extra_for_last = 0; - tree_view->priv->last_extra_space = extra; - } + minimum_width = tree_view->priv->minimum_width; + natural_width = tree_view->priv->natural_width; + n_expand_columns = tree_view->priv->n_expand_columns; - if (number_of_expand_columns > 0) - extra_per_column = extra/number_of_expand_columns; - else - extra_per_column = 0; + width = MAX (widget_allocation.width, minimum_width); - if (update_expand) + /* We change the width here. The user might have been resizing columns, + * which changes the total width of the tree view. This is of + * importance for getting the horizontal scroll bar right. + */ + if (tree_view->priv->width != width) { - tree_view->priv->last_extra_space_per_column = extra_per_column; - tree_view->priv->last_number_of_expand_columns = number_of_expand_columns; + tree_view->priv->width = width; + if (width_changed) + *width_changed = TRUE; } - for (list = (rtl ? last_column : first_column); - list != (rtl ? first_column->prev : last_column->next); - list = (rtl ? list->prev : list->next)) + /* iterate through columns in reverse order */ + for (list = (rtl ? first_column : last_column); + list != (rtl ? last_column->next : first_column->prev); + list = (rtl ? list->next : list->prev)) { - gint column_width; - column = list->data; if (!gtk_tree_view_column_get_visible (column) || column == tree_view->priv->drag_column) continue; - column_width = _gtk_tree_view_column_request_width (column); + _gtk_tree_view_column_request_width (column, &column_minimum, &column_natural); + + column_width = column_natural; - if (gtk_tree_view_column_get_expand (column)) - { - if (number_of_expand_columns == 1) + if (width > natural_width) + { + /* We need to expand some columns. If there are none marked to + * expand, give all the extra space to the last column. */ + if (n_expand_columns == 0) { - /* We add the remander to the last column as - * */ - column_width += extra; + column_width = column_natural + (width - natural_width); } - else + else if (gtk_tree_view_column_get_expand (column)) { - column_width += extra_per_column; - extra -= extra_per_column; - number_of_expand_columns --; + column_width = column_natural + (width - natural_width) / n_expand_columns; + n_expand_columns--; } - } - else if (number_of_expand_columns == 0 && - list == last_column) + } + else if (width < natural_width) { - column_width += extra; + /* We need to shrink some columns. Starting with later columns, + * shrink each one down to its minimum width as necessary. */ + column_width = MAX (column_natural + (width - natural_width), column_minimum); } - - /* In addition to expand, the last column can get even more - * extra space so all available space is filled up. - */ - if (extra_for_last > 0 && list == last_column) - column_width += extra_for_last; - - _gtk_tree_view_column_allocate (column, width, column_width); - - width += column_width; - } - - /* We change the width here. The user might have been resizing columns, - * which changes the total width of the tree view. This is of - * importance for getting the horizontal scroll bar right. - */ - if (tree_view->priv->width != width) - { - tree_view->priv->width = width; - if (width_changed) - *width_changed = TRUE; + + _gtk_tree_view_column_allocate (column, width - column_width, column_width); + + minimum_width -= column_minimum; + natural_width -= column_natural; + width -= column_width; } } @@ -6062,7 +6027,6 @@ validate_row (GtkTreeView *tree_view, _gtk_rbtree_node_set_height (tree, node, height); } _gtk_rbtree_node_mark_valid (tree, node); - tree_view->priv->post_validation_flag = TRUE; return retval; } diff --git a/gtk/gtktreeviewcolumn.c b/gtk/gtktreeviewcolumn.c index 6a47dbe89a..3f32c81312 100644 --- a/gtk/gtktreeviewcolumn.c +++ b/gtk/gtktreeviewcolumn.c @@ -2092,48 +2092,48 @@ gtk_tree_view_column_get_x_offset (GtkTreeViewColumn *tree_column) return tree_column->priv->x_offset; } -gint -_gtk_tree_view_column_request_width (GtkTreeViewColumn *tree_column) +void +_gtk_tree_view_column_request_width (GtkTreeViewColumn *tree_column, + gint *minimum, + gint *natural) { - GtkTreeViewColumnPrivate *priv; - gint real_requested_width; - - priv = tree_column->priv; + GtkTreeViewColumnPrivate *priv = tree_column->priv; + gint minimum_width = 1, natural_width = 1; + gint button_minimum, button_natural; - if (priv->fixed_width != -1) - { - real_requested_width = priv->fixed_width; - } - else if (gtk_tree_view_get_headers_visible (GTK_TREE_VIEW (priv->tree_view))) + if (priv->column_type != GTK_TREE_VIEW_COLUMN_FIXED) { - gint button_request; - gint requested_width; + gtk_cell_area_context_get_preferred_width (priv->cell_area_context, &minimum_width, &natural_width); + minimum_width += priv->padding; + natural_width += priv->padding; - gtk_cell_area_context_get_preferred_width (priv->cell_area_context, &requested_width, NULL); - requested_width += priv->padding; - - gtk_widget_get_preferred_width (priv->button, &button_request, NULL); - real_requested_width = MAX (requested_width, button_request); + if (gtk_tree_view_get_headers_visible (GTK_TREE_VIEW (priv->tree_view))) + { + gtk_widget_get_preferred_width (priv->button, &button_minimum, &button_natural); + minimum_width = MAX (minimum_width, button_minimum); + natural_width = MAX (natural_width, button_natural); + } } - else - { - gint requested_width; - gtk_cell_area_context_get_preferred_width (priv->cell_area_context, &requested_width, NULL); - requested_width += priv->padding; - - real_requested_width = requested_width; - if (real_requested_width < 0) - real_requested_width = 0; - } + if (priv->fixed_width != -1) + natural_width = MAX (priv->fixed_width, minimum_width); if (priv->min_width != -1) - real_requested_width = MAX (real_requested_width, priv->min_width); + { + minimum_width = MAX (minimum_width, priv->min_width); + natural_width = MAX (natural_width, priv->min_width); + } if (priv->max_width != -1) - real_requested_width = MIN (real_requested_width, priv->max_width); + { + minimum_width = MIN (minimum_width, priv->max_width); + natural_width = MIN (natural_width, priv->max_width); + } - return real_requested_width; + if (minimum != NULL) + *minimum = minimum_width; + if (natural != NULL) + *natural = natural_width; } void -- 2.30.2